package algo;

import java.util.HashMap;

public class ResultsQualityEvaluator
{
	private HashMap<Context, Result> results;
	private int mailsSize;
	private int[] nearNeighborsSizes;
	private NearNeighborsEvaluator[] nearNeighborsEvaluators;
	private float[] toggleProbabilitys;
	
	
	public ResultsQualityEvaluator(int mailsSize, int[] nearNeighborsSizes, NearNeighborsEvaluator[] nearNeighborsEvaluators, float[] toggleProbabilitys)
	{
		this.mailsSize = mailsSize;
		this.nearNeighborsSizes = nearNeighborsSizes;
		this.nearNeighborsEvaluators = nearNeighborsEvaluators;
		this.toggleProbabilitys = toggleProbabilitys;
		
		results = new HashMap<Context, Result>();
		for (int nearNeighborsSize : nearNeighborsSizes)
		{
			for (NearNeighborsEvaluator nearNeighborsEvaluator : nearNeighborsEvaluators)
			{
				for (float toggleProbability : toggleProbabilitys)
				{
					results.put(new Context(nearNeighborsSize, nearNeighborsEvaluator, toggleProbability), new Result());
				}
			}
		}
	}

	public Result getResult(Context context)
	{
		return results.get(context);
	}
	
	public int[] getNearNeighborsSizes()
	{
		return nearNeighborsSizes;
	}

	public NearNeighborsEvaluator[] getNearNeighborsEvaluators()
	{
		return nearNeighborsEvaluators;
	}

	public float[] getToggleProbabilitys()
	{
		return toggleProbabilitys;
	}
	
	public class Result
	{
		private int truePositive;
		private int trueNegative;
		private int falsePositive;
		private int falseNegative;
		
		
		public Result()
		{
			this(0, 0, 0, 0);
		}
		
		public Result(int truePositive, int trueNegative, int falsePositive, int falseNegative)
		{
			this.truePositive = truePositive;
			this.trueNegative = trueNegative;
			this.falsePositive = falsePositive;
			this.falseNegative = falseNegative;
		}
		
		public void add(boolean isSpam, boolean isDetectedAsSpam)
		{
			if (isDetectedAsSpam)
			{
				if (isSpam)
				{
					truePositive++;
				}
				else
				{
					falsePositive++;
				}
			}
			else
			{
				if (isSpam)
				{
					falseNegative++;
				}
				else
				{
					trueNegative++;
				}
			}
		}
		
		public float getAccuracy()
		{
			return (float) (truePositive + trueNegative) / mailsSize;
		}
		
		public float getPrecision()
		{
			return (float) truePositive / ( truePositive + falsePositive);
		}
		
		public float getSensitivity()
		{
			return (float) truePositive / (truePositive + falseNegative);
		}
		
		public float getSpecificity()
		{
			return 1 - (float) falsePositive / (trueNegative + falsePositive);
		}

		public int getTruePositive()
		{
			return truePositive;
		}

		public int getTrueNegative()
		{
			return trueNegative;
		}

		public int getFalsePositive()
		{
			return falsePositive;
		}

		public int getFalseNegative()
		{
			return falseNegative;
		}
	}
}
